//
//  AppDelegate.swift
//  SitPosition
//
//  Created by apple on 2018/12/22.
//  Copyright © 2018 apple. All rights reserved.
//

import UIKit
import Toast_Swift
import INSPhotoGallery
import AlamofireNetworkActivityIndicator

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    
    // 微信API代理
    public weak var wxApiDelegate: WXApiDelegate? = nil
    // 支付宝代理
    public weak var aliPayDelegate: AliPayDelegate? = nil
    // 是否正在询问用户身份？
    public var isAskingUserRole: Bool = false
    // 改变屏幕亮度的串行队列
    private let brightnessUpdateQueue: OperationQueue = {
        let queue = OperationQueue()
        queue.maxConcurrentOperationCount = 1
        return queue
    }()
    // App收到外部Event的回调
    public var onSendEvent: ((_ event: UIEvent) -> Void)? = nil {
        didSet {
            // 监听App的Event
            let application: SPApplication = UIApplication.shared as! SPApplication
            application.onSendEvent = onSendEvent
        }
    }
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // 初始化用户设置
        Preferences.onAppLaunch()
        
        // 注册通知
        _registerNotifications()
        
        // 初始化三方SDK
        _initializeSDKs(application, launchOptions: launchOptions)
        
        // 初始化网络组件
        OAuth2Handler.accessTokenGetter = {
            return UserManager.manager.user?.accessToken
        }
        OAuth2Handler.accessTokenSetter = { accessToken in
            UserManager.manager.updateAccessToken(accessToken)
            NetworkClient.instance.accessToken = accessToken.access_token
        }
        
        // 准备Window和根VC
        let nav = UINavigationController(rootViewController: HomeViewController())
        window = UIWindow()
        window?.frame = UIScreen.main.bounds
        window?.rootViewController = nav
        window?.makeKeyAndVisible()
        
        // 启动姿态数据推送管理器，必须在上传管理器启动前启动它
        StudyDataPushManager.manager.start()
        
        // 恢复UserManager
        UserManager.manager.onAppLaunch()
        
        // 用户登录流程
        nav.showLoginViewControllerIfNeeded(true)
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
        EMClient.shared()?.applicationDidEnterBackground(application)
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
        EMClient.shared()?.applicationWillEnterForeground(application)
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
    
    func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
        return _openURL(url)
    }
    
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        return _openURL(url)
    }
    
    // MARK: - Public Methods
    
    // 渐进改变屏幕亮度
    // @value - 屏幕亮度
    public func graduallySetBrightness(_ value: CGFloat) {
        brightnessUpdateQueue.cancelAllOperations()
        
        let brightness: CGFloat = UIScreen.main.brightness
        let step: CGFloat = 0.005 * ((value > brightness) ? 1.0 : -1.0)
        let times: Int = Int(abs((value - brightness) / 0.005))
        for i in 0..<times {
            brightnessUpdateQueue.addOperation {
                Thread.sleep(forTimeInterval: 1.0 / 180.0)
                UIScreen.main.brightness = brightness + CGFloat(i+1) * step
            }
        }
    }
    
}

// MARK: - Private Methods

extension AppDelegate {
    
    // 注册通知
    private func _registerNotifications() {
        
        // 用户登录成功通知
        NotificationCenter.default.addObserver(forName: UserLoginSuccess, object: nil, queue: OperationQueue.main) { [weak self] _ in
            self?._loginIMAccount()
            UserConfigs.refreshCurrentUserConfigs { _ in }
            UploadManager.manager.currentUserId = UserManager.manager.user?.id
            UploadManager.manager.start()
        }
        // 用户注销成功通知
        NotificationCenter.default.addObserver(forName: UserLogedout, object: nil, queue: OperationQueue.main) { [weak self] _ in
            self?._logoutIMAccount()
            UploadManager.manager.currentUserId = nil
        }
        // 询问用户角色
        NotificationCenter.default.addObserver(forName: UserAskRole, object: nil, queue: OperationQueue.main) { [weak self] _ in
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+1.0, execute: {
                self?._askUserRole()
            })
        }
        // 用户令牌失效通知
        NotificationCenter.default.addObserver(forName: AccessTokenInvalid, object: nil, queue: OperationQueue.main) { _ in
            UserManager.manager.logout()
        }
    }
    
    // 初始化三方SDK
    private func _initializeSDKs(_ application: UIApplication, launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
        // Bugly
        Bugly.start(withAppId: "62faac8950")
        
        // Toast
        ToastManager.shared.position = .center
        ToastManager.shared.duration = Theme.Toast.normalDuration
        
        // Alamofire
        NetworkActivityIndicatorManager.shared.isEnabled = true
        
        /**
         * 环信
         */
        let ringIMAppKey: String = "1121181129157362#sitposition"
        #if DEBUG
        let ringIMApnsCertName: String = "sitposition-apns-dev"
        #else
        let ringIMApnsCertName: String = "sitposition-apns"
        #endif
        
        // 环信SDK
        let options: EMOptions = EMOptions(appkey: ringIMAppKey)
        options.apnsCertName = ringIMApnsCertName
        options.isAutoAcceptGroupInvitation = false
        EMClient.shared()?.initializeSDK(with: options)
        
        // 环信UI
        let otherConfig: [AnyHashable : Any] = [
            "isUselibHyphenateClientSDKLite" : false,
            "SDKConfigEnableConsoleLogger" : true,
            "httpsOnly" : true
        ]
        EaseSDKHelper.share()?
            .hyphenateApplication(application,
                                  didFinishLaunchingWithOptions: launchOptions,
                                  appkey: ringIMAppKey,
                                  apnsCertName: ringIMApnsCertName,
                                  otherConfig: otherConfig)
        if let readManager = EaseMessageReadManager.defaultManager() as? EaseMessageReadManager {
            readManager.showImagesHandler = { (imgObjs) in
                guard let imgObjs_ = imgObjs,
                    !imgObjs_.isEmpty else {
                    return
                }
                var photos: [INSPhoto] = []
                for imgObj in imgObjs_ {
                    if let image = imgObj as? UIImage {
                        let photo: INSPhoto = INSPhoto(image: image, thumbnailImage: nil)
                        photos.append(photo)
                    } else if let urlString = imgObj as? String,
                        let url = URL(string: urlString) {
                        let photo: INSPhoto = INSPhoto(imageURL: url, thumbnailImage: nil)
                        photos.append(photo)
                    }
                }
                guard !photos.isEmpty else { return }
                let galleryPreview = INSPhotosViewController(photos: photos, initialPhoto: photos[0], referenceView: nil)
                UIApplication.shared.topmostViewController?
                    .present(galleryPreview, animated: true, completion: nil)
            }
        }
        
        /**
         * 支付SDK
         */
        WXApi.registerApp("wx0ddf0020c190bbd0")
    }
    
    // 登录环信账号
    private func _loginIMAccount() {
        UserManager.manager.user?.ringAccount?.forEach({ (imAccount: User.IMAccount) in
            ChatUserCacheInfo.update(by: imAccount.id,
                                     nickName: (imAccount.nickname ?? imAccount.id),
                                     avatarUrl: nil)
        })
        guard let imAccount = UserManager.manager.userIMAcount else { return }
        
        DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
            
            let error = EMClient.shared()?.login(withUsername: imAccount.id, password: imAccount.password)
            DispatchQueue.main.async { [weak self] in
                if let error_ = error, error_.code != EMErrorUserAlreadyLogin {
                    let message: String
                    message = error_.errorDescription
                    self?.window?.makeToast(message)
                } else {
                    EMClient.shared()?.options.isAutoLogin = true
                }
            }
        }
    }
    
    // 登出环信账号
    private func _logoutIMAccount() {
        EMClient.shared()?.logout(true)
    }
    
    private func _reloginIMAccount() {
        _logoutIMAccount()
        _loginIMAccount()
    }
    
    // 支付SDK的openURL请求
    func _openURL(_ url: URL) -> Bool {
        if (url.host == "safepay") {
            // 跳转支付宝钱包进行支付，处理支付结果
            AlipaySDK.defaultService()?.processOrder(withPaymentResult: url, standbyCallback: { [weak self] (resultDict) in
                self?.aliPayDelegate?.alipayResponse(resultDict)
            })
            return true
        }
        
        if let delegate = wxApiDelegate {
            return WXApi.handleOpen(url, delegate: delegate)
        }
        return false
    }
    
    // 询问用户登录的角色
    private func _askUserRole() {
        guard !isAskingUserRole else { return }
        isAskingUserRole = true
        
        let alert: UIAlertController = UIAlertController(title: Strings.logonTitle, message: Strings.logoAskUserRole, preferredStyle: UIAlertController.Style.alert)
        alert.addAction(UIAlertAction(title: Strings.logoUserRoleStudent, style: UIAlertAction.Style.default, handler: { [unowned self] (action) in
            UserManager.manager.role = UserRole.student
            self.isAskingUserRole = false
            self._reloginIMAccount()
        }))
        alert.addAction(UIAlertAction(title: Strings.logoUserRoleParent, style: UIAlertAction.Style.default, handler: { [unowned self] (action) in
            UserManager.manager.role = UserRole.parent
            self.isAskingUserRole = false
            self._reloginIMAccount()
        }))
        UIApplication.shared.topmostViewController?
            .present(alert, animated: true, completion: nil)
    }
}
